home *** CD-ROM | disk | FTP | other *** search
/ Aminet 16 / Aminet 16 (1996)(GTI - Schatztruhe)[!][Dec 1996].iso / Aminet / misc / emu / QDOS2.lha / QLsource / ROMsrc / CLK / CLK_asm
Text File  |  1995-07-25  |  12KB  |  548 lines

  1.     SECTION    CLK
  2.  
  3.     INCLUDE    '/INC/QDOS_inc'
  4.     INCLUDE    '/INC/AMIGA_inc'
  5.     INCLUDE    '/INC/AMIGQDOS_inc'
  6.  
  7. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  8. ; CLK_asm - Clock routines
  9. ;     - last modified 25/07/95
  10.  
  11. ; All the necessary clock related sources, required to
  12. ; implement QDOS clock routines on the Amiga computer.
  13.  
  14. ; Amiga-QDOS sources by Rainer Kowallik
  15. ;    ...latest changes by Mark J Swift
  16.  
  17. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  18. ;  ROM header
  19.  
  20. BASE:
  21.     dc.l    $4AFB0001    ; ROM recognition code
  22.     dc.w    0
  23.     dc.w    ROM_START-BASE
  24.     dc.b    0,32,'Amiga-QDOS CLOCK routines v1.12',$A
  25.  
  26. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  27. ;  start of ROM code
  28.  
  29. ROM_START:
  30.     movem.l    d0-d2/a0-a3,-(a7)
  31.  
  32. ; --------------------------------------------------------------
  33. ;  allocate memory for CLK patch variables
  34.  
  35.     move.l    #CV_LEN,d1
  36.     moveq    #MT.ALCHP,d0
  37.     moveq    #0,d2
  38.     trap    #1
  39.  
  40. ; --------------------------------------------------------------
  41. ;  address of CLK patch variables
  42.  
  43.     move.l    a0,AV.CLKV
  44.     move.l    a0,a3
  45.  
  46. ; --------------------------------------------------------------
  47. ;  enter supervisor mode and disable interrupts
  48.  
  49.     trap    #0
  50.  
  51.     ori.w    #$0700,sr    ; disable interrupts
  52.  
  53. ; --------------------------------------------------------------
  54. ;  link a custom routine into RESET routine
  55.  
  56.     lea    AV.RSETlink,a1
  57.     lea    CV.RSETlink(a3),a2
  58.  
  59.     move.l    (a1),(a2)
  60.     move.l    a2,(a1)
  61.  
  62.     lea    MY_RSET(pc),a1
  63.     move.l    a1,$04(a2)
  64.  
  65. ; --------------------------------------------------------------
  66. ;  link a custom routine into level 7 interrupt server
  67.  
  68.     lea    AV.LVL7link,a1
  69.     lea    CV.LVL7link(a3),a2
  70.  
  71.     move.l    (a1),(a2)
  72.     move.l    a2,(a1)
  73.  
  74.     lea    MY_LVL7(pc),a1
  75.     move.l    a1,$04(a2)
  76.  
  77. ; --------------------------------------------------------------
  78. ;  link a custom routine into Trap #1 exception
  79.  
  80.     lea    AV.TRP1link,a1
  81.     lea    CV.TRP1link(a3),a2
  82.  
  83.     move.l    (a1),(a2)
  84.     move.l    a2,(a1)
  85.  
  86.     lea    MY_TRP1(pc),a1
  87.     move.l    a1,$04(a2)
  88.  
  89. ; --------------------------------------------------------------
  90. ;  Read Amiga clock and set QDOS clock
  91.  
  92.     bsr.s    INIT_HW
  93.  
  94.     andi.w    #$D8FF,sr    ; enable ints, enter user
  95.  
  96.     ifd    isA500
  97.  
  98.     bne.s    ADD_XINT     ; skip if clock exists
  99.  
  100.     lea    CLK_MESS(pc),a1    ; start of message
  101.     suba.l    a0,a0        ; output channel 0
  102.     move.w    UT.MTEXT,a2
  103.     jsr    (a2)        ; print it
  104.  
  105.     endif
  106. ; -------------------------------------------------------------
  107. ; link in external interrupt to act on blitter
  108.  
  109. ADD_XINT:
  110.     move.l    AV.CLKV,a3
  111.  
  112.     lea    XINT_SERv(pc),a1    ; address of routine
  113.     lea    CV.XINTLink(a3),a0
  114.     move.l    a1,4(a0)
  115.     moveq    #MT.LXINT,d0
  116.     trap    #1
  117.  
  118. ; --------------------------------------------------------------
  119. ROM_EXIT:
  120.     movem.l    (a7)+,d0-d2/a0-a3
  121.     rts
  122.  
  123. CLK_MESS:
  124.     dc.b    0,33,' clock initialised from AmigaDOS',10,0
  125.  
  126. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  127. ;  subroutine to read AMIGA clock and initialise QDOS clock
  128.  
  129. INIT_HW:
  130.     movem.l    d0-d3/a0/a3,-(a7)
  131.  
  132.     ifd    isA500
  133.  
  134.     bsr    INITCLK
  135.     move.l    d1,d4        ; hardware clock into d4
  136.  
  137.     bclr    #7,CIAA_CRB    ; next write is to counter
  138.     move.b    #0,CIAA_EMSB    ; reset event counter
  139.     move.b    #0,CIAA_EMID
  140.     move.b    #0,CIAA_ELSB
  141.  
  142.     clr.b    d1
  143.  
  144. WAITCLK1:
  145.     move.b    d1,d2
  146.     moveq    #-1,d3
  147.  
  148. WAITCLK2:
  149.     move.b    CIAA_ELSB,D1    ; bits 0-7
  150.     cmp.b    #75,D0
  151.     bge.s    INIT_HW1     ; wait about 1.5 secs
  152.  
  153.     cmp.b    d1,d2
  154.     bne.s    WAITCLK1
  155.  
  156.     dbra    d3,WAITCLK2    ; don't wait too long
  157.  
  158. INIT_HW1:
  159.     bsr    INITCLK        ; check clock again
  160.  
  161.     move.l    d1,d0
  162.     sub.l    d4,d0
  163.     ble.s    INIT_HW2     ; no difference, no clock
  164.  
  165.     subq.l    #3,d0        ; difference greater than 3?
  166.     bcs.s    INIT_HW3     ; nope, clock functional
  167.  
  168.     endif
  169.  
  170. INIT_HW2:
  171.     moveq    #0,d0
  172.     move.l    PC_CLOCK,d1    ; get date from QL h/w
  173.  
  174. INIT_HW3:
  175.     move.l    d1,PC_CLOCK    ; set date
  176.  
  177.     move.b    #%00000100,CIAA_ICR ; disable ALARM interrupt
  178.  
  179.     bclr    #7,CIAA_CRB    ; next write is to counter
  180.     move.b    #0,CIAA_EMSB    ; reset event counter
  181.     move.b    #0,CIAA_EMID
  182.     move.b    #0,CIAA_ELSB
  183.  
  184.     bset    #7,CIAA_CRB    ; next write is to ALARM
  185.     move.b    #2,CIAA_EMSB    ; alarm every hour - so
  186.     move.b    #191,CIAA_EMID    ; as to update clock from
  187.     move.b    #32,CIAA_ELSB    ; event counter.
  188.  
  189.     move.b    CIAA_ICR,d7    ; read & clear CIA-A ICR
  190.     or.b    AV.CIAA_ICR,d7
  191.     bclr    #2,d7        ; clear ALARM bit
  192.     move.b    d7,AV.CIAA_ICR    ; store for another program
  193.  
  194.     move.w    #%0000000000001000,INTREQ ; clear and enable
  195.     move.w    #%1000000000001000,INTENA ; CIA-A interrupts
  196.  
  197.     move.b    #%10000100,CIAA_ICR ; enable ALARM interrupt
  198.  
  199.     ori.b    #%00000100,AV.CIAA_MSK ; take note of alarm
  200.  
  201.     tst.l    d0
  202.  
  203.     movem.l    (a7)+,d0-d3/a0/a3
  204.     rts
  205.  
  206. ; --------------------------------------------------------------
  207.     ifd    isA500
  208.  
  209. INITCLK:
  210.     moveq    #0,d2        ; fetch year (i.e. 91)
  211.     move.b    CLK_YYH,d2
  212.     andi.b    #$0F,d2
  213.     mulu.w    #10,d2
  214.     move.b    CLK_YYL,d3
  215.     andi.b    #$0F,d3
  216.     add.b    d3,d2
  217.  
  218.     cmpi.b    #78,d2        ; years before 1978 should
  219.     bge.s    INITCLK1     ; be read as 20xx i.e 2077
  220.  
  221.     addi.b    #100,d2
  222.  
  223. ; --------------------------------------------------------------
  224. INITCLK1:
  225.     subi.b    #61,d2        ; relative to 1961
  226.     move.l    d2,d0        ; make a copy
  227.     mulu.w    #365,d2
  228.  
  229.     move.l    d2,d1        ; accumulate date in d1
  230.  
  231. ; --------------------------------------------------------------
  232.     moveq    #0,d2        ; fetch month
  233.     move.b    CLK_MMH,d2
  234.     andi.b    #$0F,d2
  235.     mulu.w    #10,d2
  236.     move.b    CLK_MML,d3
  237.     andi.b    #$0F,d3
  238.     add.b    d3,d2
  239.  
  240.     divu.w    #4,d0        ; test for leap year
  241.  
  242.     swap    d0
  243.     cmpi.w    #3,d0        ; is it a leap year?
  244.     bne.s    INITCLK2     ; ...no
  245.  
  246.     cmpi.w    #2,d2        ; is it after february?
  247.     ble.s    INITCLK2     ; ...no
  248.  
  249.     addq.l    #1,d1        ; compensate for extra day
  250.  
  251. ; --------------------------------------------------------------
  252. INITCLK2:
  253.     clr.w    d0
  254.     swap    d0        ; clear high 16 bits of d0
  255.  
  256.     add.l    d0,d1        ; add in previous leap years
  257.  
  258. ; --------------------------------------------------------------
  259.     subq.l    #1,d2        ; month number now (0...11)
  260.     asl.w    #1,d2        ; offset into table
  261.     lea    DAYTBL(pc),a0
  262.     move.w    0(a0,d2.w),d2    ; cumulative total to d2
  263.  
  264.     add.l    d2,d1        ; add it to date
  265.  
  266. ; --------------------------------------------------------------
  267.     moveq    #0,d2        ; fetch day
  268.     move.b    CLK_DDH,d2
  269.     andi.b    #$0F,d2
  270.     mulu.w    #10,d2
  271.     move.b    CLK_DDL,d3
  272.     andi.b    #$0F,d3
  273.     add.b    d3,d2
  274.  
  275.     subq.w    #1,d2        ; compensate for day zero
  276.  
  277.     add.l    d2,d1        ; add it to date
  278.  
  279. ; --------------------------------------------------------------
  280.     moveq    #24,d0        ; convert days to hours
  281.     bsr    MULT
  282.  
  283.     moveq    #0,d2        ; fetch hour
  284.     move.b    CLK_HRH,d2
  285.     andi.b    #$0F,d2
  286.     mulu.w    #10,d2
  287.     move.b    CLK_HRL,d3
  288.     andi.b    #$0F,d3
  289.     add.b    d3,d2
  290.  
  291.     add.l    d2,d1        ; add it to date
  292.  
  293. ; --------------------------------------------------------------
  294.     moveq    #60,d0        ; convert hours to minutes
  295.     bsr.s    MULT
  296.  
  297.     moveq    #0,d2        ; fetch minute
  298.     move.b    CLK_MNH,d2
  299.     andi.b    #$0F,d2
  300.     mulu.w    #10,d2
  301.     move.b    CLK_MNL,d3
  302.     andi.b    #$0F,d3
  303.     add.b    d3,d2
  304.  
  305.     add.l    d2,d1        ; add it to date
  306.  
  307. ; --------------------------------------------------------------
  308.     moveq    #60,d0        ; convert minutes to secs
  309.     bsr.s    MULT
  310.  
  311.     moveq    #0,d2        ; fetch seconds
  312.     move.b    CLK_SCH,d2
  313.     andi.b    #$0F,d2
  314.     mulu.w    #10,d2
  315.     move.b    CLK_SCL,d3
  316.     andi.b    #$0F,d3
  317.     add.b    d3,d2
  318.  
  319.     add.l    d2,d1        ; add it to date
  320.  
  321.     rts
  322.  
  323.     endif
  324.  
  325. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  326. ;  table of cumulative totals of length of each month
  327.  
  328. DAYTBL:
  329.     dc.w    0,31,59,90,120,151,181,212,243,273,304,334
  330.  
  331. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  332. ;  multiply 32 bit d1 by 16 bit d0 (assumes no overflow)
  333.  
  334. MULT:
  335.     move.l    d1,d2        ; make copy
  336.  
  337.     swap    d1        ; multiply high word
  338.     mulu.w    d0,d1
  339.     swap    d1
  340.     clr.w    d1
  341.  
  342.     mulu.w    d0,d2        ; multiply low word
  343.  
  344.     add.l    d2,d1
  345.  
  346.     rts
  347.  
  348. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  349. ;  Custom RSET routine to update the clock before a system reset
  350.  
  351. MY_RSET:
  352.     bsr    UPDT_CLK
  353.  
  354.     subq.l    #4,a7
  355.     movem.l    a3,-(a7)
  356.     move.l    AV.CLKV,a3
  357.     move.l    CV.RSETlink(a3),a3
  358.     move.l    4(a3),4(a7)    ; address of next routine
  359.     movem.l    (a7)+,a3
  360.  
  361.     rts
  362.  
  363. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  364. ;  Custom LVL7 routine to initialise hardware
  365.  
  366. MY_LVL7:
  367.     bsr    INIT_HW
  368.  
  369.     subq.l    #4,a7
  370.     movem.l    a3,-(a7)
  371.     move.l    AV.CLKV,a3
  372.     move.l    CV.LVL7link(a3),a3
  373.     move.l    4(a3),4(a7)    ; address of next routine
  374.     movem.l    (a7)+,a3
  375.  
  376.     rts
  377.  
  378. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  379. ;  A patch to replace TRAP#1 calls to:
  380. ;  MT_RCLCK (d0=$13), MT_SCLCK (d0=$14), MT_ACLCK (d0=$15)
  381.  
  382. MY_TRP1:
  383.     bsr.s    INI_A5A6
  384.  
  385.     cmp.b    #MT.RCLCK,d0
  386.     beq.s    MT_RCLCK
  387.  
  388.     cmp.b    #MT.SCLCK,d0
  389.     beq.s    MT_SCLCK
  390.  
  391.     cmp.b    #MT.ACLCK,d0
  392.     beq.s    MT_ACLCK
  393.  
  394.     movem.l    (a7)+,d7/a5/a6    ; restore registers
  395.  
  396.     subq.l    #4,a7
  397.     movem.l    a3,-(a7)
  398.     move.l    AV.CLKV,a3
  399.     move.l    CV.TRP1link(a3),a3
  400.     move.l    4(a3),4(a7)    ; address of next routine
  401.     movem.l    (a7)+,a3
  402.  
  403.     rts
  404.  
  405. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  406. ; initialise A5 and A6 prior to performing a TRAP routine
  407.  
  408. INI_A5A6
  409.     SUBQ.L    #8,A7
  410.     MOVE.L    8(A7),-(A7)
  411.     MOVEM.L    D7/A5/A6,4(A7)
  412.  
  413.     move.l    a7,d7
  414.     andi.l    #$FFFF8000,d7
  415.     move.l    d7,a6        ; Calc address of sys vars
  416.  
  417.     LEA    4(A7),A5     ; A5 points to saved
  418.                 ; Registers D7,A5,A6
  419.     MOVEQ    #$7F,D7
  420.     AND.L    D7,D0
  421.     RTS
  422.  
  423. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  424. ;  TRAP #1 with D0=$13
  425. ;  implement clock (CIA-A event counter)/50+PC_CLOCK
  426.  
  427. MT_RCLCK:
  428.     bsr    UPDT_CLK
  429.  
  430.     moveq    #0,d0        ; no errors
  431.     bra.s    TRAP1_X
  432.  
  433. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  434. ;  TRAP #1 with D0=$14
  435.  
  436. MT_SCLCK:
  437.     move.l    d1,PC_CLOCK    ; use this as new offset
  438.  
  439.     bclr    #7,CIAA_CRB    ; next write is to counter
  440.     move.b    #0,CIAA_EMSB    ; reset event counter
  441.     move.b    #0,CIAA_EMID
  442.     move.b    #0,CIAA_ELSB
  443.  
  444.     moveq    #0,d0        ; no errors
  445.     bra.s    TRAP1_X
  446.  
  447. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  448. ;  TRAP #1 with D0=$15
  449.  
  450. MT_ACLCK:
  451.     add.l    d1,PC_CLOCK    ; adjust increment offset
  452.  
  453.     moveq    #0,d0        ; no errors
  454.  
  455. ; --------------------------------------------------------------
  456. ;  exit from TRAP call
  457.  
  458. TRAP1_X    movem.l    (a7)+,d7/a5/a6    ; exit from exception
  459.     rte
  460.  
  461. ; --------------------------------------------------------------
  462. UPDT_CLK:
  463.     MOVEQ.L    #0,D1
  464.     MOVE.B    CIAA_EMSB,D1    ; read bits 16-23
  465.     LSL.L    #8,D1
  466.     MOVE.B    CIAA_EMID,D1    ; bits 8-15
  467.     LSL.L    #8,D1
  468.     MOVE.B    CIAA_ELSB,D1    ; bits 0-7
  469.     DIVU    #5000,D1     ; 100 seconds
  470.     MOVEQ    #0,D0
  471.     MOVE.W    D1,D0        ; get quotient
  472.     MULU    #100,D0        ; get seconds so far
  473.     SWAP    D1
  474.     AND.L    #$FFFF,D1    ; get remainder
  475.     DIVU    #50,D1        ; get seconds
  476.  
  477.     bclr    #7,CIAA_CRB    ; next write is to counter
  478.     move.b    #0,CIAA_EMSB
  479.     move.b    #0,CIAA_EMID
  480.     move.b    #0,CIAA_ELSB
  481.  
  482.     ;swap     d1         ; get ticks remaining
  483.     ;move.b     d1,CIAA_ELSB     ; restart counter
  484.     ;swap     d1
  485.  
  486.     AND.L    #$FFFF,D1    ; get quotient
  487.     ADD.L    D0,D1        ; seconds complete
  488.     add.l    PC_CLOCK,d1    ; add offset for actual day
  489.                 ; and time
  490.     move.l    d1,PC_CLOCK    ; update QL h/w
  491.  
  492.     rts
  493.  
  494. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  495. ;  external interrupt server
  496.  
  497. XINT_SERv:
  498.     movem.l    d7/a0,-(a7)
  499.  
  500.     move.w    INTENAR,d7    ; read interrupt enable reg
  501.     btst    #3,d7        ; branch if ints not on
  502.     beq    XINT_OTHer
  503.  
  504.     move.w    INTREQR,d7    ; read interrupt request reg
  505.     btst    #3,d7        ; branch if from CIA-A or
  506.     bne    CIAA_SERv    ; expansion ports
  507.  
  508. ; --------------------------------------------------------------
  509. ;  otherwise let another external interrupt server handle it
  510.  
  511. XINT_OTHer:
  512.     movem.l    (a7)+,d7/a0
  513.     rts
  514.  
  515. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  516. ;  Interrupt from CIA-A or expansion port
  517.  
  518. CIAA_SERv:
  519.     move.b    CIAA_ICR,d7    ; read CIA-A ICR
  520.     or.b    AV.CIAA_ICR,d7
  521.     move.b    d7,AV.CIAA_ICR    ; store for another program
  522.  
  523.     bclr    #2,d7        ; (ALARM bit=1)
  524.     beq    XINT_OTHer    ; no
  525.  
  526. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  527. ;  External interrupt server for acting on event counter alarm
  528. ;  (CIAA ALARM bit=1).
  529.  
  530. ALRM_SERv:
  531.     move.b    d7,AV.CIAA_ICR
  532.  
  533.     and.b    AV.CIAA_MSK,d7    ; don't clear INTREQ if
  534.     bne.s    ALRM_0        ; other CIAA ints occured
  535.  
  536.     move.w    #%0000000000001000,INTREQ ; clear interrupts
  537.  
  538. ; -------------------------------------------------------------
  539. ALRM_0:
  540.     bsr    UPDT_CLK     ; update clock
  541.  
  542. ; -------------------------------------------------------------
  543. XINT_EXIt:
  544.     bra    XINT_OTHer
  545.  
  546. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  547.     END
  548.